﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DynaPrecision.LinearSystem
{
	public class Array2DOperator
	{

		public static void Times<TResult, T>(IMultiDimensionalArray<T> left, IMultiDimensionalArray<T> right, TResult result)
			where TResult : IInitializableArray<T>
		{
			if (left.GetLength(1) != right.GetLength(0))
			{
				throw new System.Exception("Cannot multiple the two arrays!");
			}
			if (result.GetLength(0) < left.GetLength(0) || result.GetLength(1) < right.GetLength(1))
			{
				result.Initiate(left.GetLength(0), right.GetLength(1));
			}
			for (int i = 0; i < result.GetLength(0); i++)
			{
				for (int j = 0; j < result.GetLength(1); j++)
				{
					result[i, j] = DefaultValueProvider<T>.Zero;
					for (int m = 0; m < left.GetLength(1); m++)
					{
						result[i, j] = result[i, j] + (dynamic)left[i, m] * right[m, j];
					}
				}
			}
		}
		public static void InhomogeniousTimesVector<TArray, TVector, TResultVector, TResult>(
			IMultiDimensionalArray<TArray> left, IVector<TVector> vector, TResultVector result, Func<TArray, TVector, TResult> MultiplicationResult)
			where TResultVector : IVector<TResult>
		{
			if (vector.Count != left.GetLength(1))
			{
				throw new System.Exception("Length not satisfactory");
			}
			int i;
			for (i = 0; i < left.GetLength(0) && i < result.Count; i++)
			{
				result[i] = DefaultValueProvider<TResult>.Zero;
				for (int j = 0; j < left.GetLength(1); j++)
				{
					result[i] = result[i] + (dynamic)MultiplicationResult(left[i, j], vector[j]);
				}
			}
			for (; i < left.GetLength(0); i++)
			{
				result.AsList().Add(DefaultValueProvider<TResult>.Zero);
				for (int j = 0; j < left.GetLength(1); j++)
				{
					result[i] = result[i] + (dynamic)MultiplicationResult(left[i, j], vector[j]);
				}
			}
		}
		public static void TimesVector<T, TVector>(IMultiDimensionalArray<T> left, IVector<T> vector, TVector result)
			where TVector : IVector<T>
		{
			if (vector.Count != left.GetLength(1))
			{
				throw new System.Exception("Length not satisfactory");
			}
			int i;
			for (i = 0; i < left.GetLength(0) && i < result.Count; i++)
			{
				result[i] = DefaultValueProvider<T>.Zero;
				for (int j = 0; j < left.GetLength(1); j++)
				{
					result[i] = result[i] + (dynamic)left[i, j] * vector[j];
				}
			}
			for (; i < left.GetLength(0); i++)
			{
				result.AsList().Add(DefaultValueProvider<T>.Zero);
				for (int j = 0; j < left.GetLength(1); j++)
				{
					result[i] = result[i] + (dynamic)left[i, j] * vector[j];
				}
			}
		}
	}
}
